<?php

/**
 * Aurorum - Open source digital signage
 *
 * @link http://digitalsignage.tk
 * @license http://www.gnu.org/licenses/gpl-3.0.html GPL v3 or later
 *
 * @category Aurorum
 * @package Aurorum
 */

/**
 * This class handles DataFrame requests.
 *
 * @package Aurorum
 * @subpackage Controllers
 */

class ADS_DataFrameController extends ADS_DefaultController{

    const STATUS_ADD_OK    = 1;
    const STATUS_REMOVE_OK = 3;
    const STATUS_EDIT_OK   = 5;
    
    const ITEM_ADD_OK      = 1;
    const ITEM_REMOVE_OK   = 3;
    const ITEM_INCREASE_OK = 5;
    const ITEM_DECREASE_OK = 7;
    const ITEM_EDIT_OK     = 9;
    
    const BULK_ACTION_REMOVE = 'remove';
    
    public function handleDefaultBulkAction(){
        //get variables
        $post   =  (array)ADS_Input::postVar('post', array()); 
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':defaultBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveFrames($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => $status
        ));
    }
    
    public function handleItemBulkAction(){
        //get variables
        $post   =  (array)ADS_Input::postVar('post', array()); 
        $action = (string)_ifset(
            ADS_Input::postVar('action1', '-1') !== '-1',
            ADS_Input::postVar('action1', '-1'),
            ADS_Input::postVar('action2', '-1')
        );
        //validate token
        if(!wp_verify_nonce(ADS_Input::postVar('token', ''), $_GET['page'].':itemBulkAction')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        //parse action
        switch ($action) {            
            case self::BULK_ACTION_REMOVE:                
                    $status = $this->bulkRemoveItems($post);                
                break;

            default:
                //action is not recognized (do nothing)
                //throw new ADS_UnknownBulkActionException('Action is not recognized.');
                break;
        }
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => $status
        ), 'frameId');
    }
    
    public function bulkRemoveFrames($frames){
        //validate parameters
        if(!is_array($frames)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();
        foreach ($frames as $frameId) {
            $this->handleRemoveFrame((int)$frameId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function bulkRemoveItems($items){
        //validate parameters
        if(!is_array($items)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        ADS_Navigator::freeze();
        foreach ($items as $itemId) {
            $this->handleRemoveItem((int)$itemId, false);
        }
        ADS_Navigator::unfreeze();        
    }
    
    public function handleRemoveFrame($frameId = 0, $useToken = true){        
        //validate parameters
        if(!is_int($frameId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeFrame')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        $dfModel = new ADS_DataFrameModel();
        //get variables
        $frameId = (int)_ifset($frameId > 0, $frameId, ADS_Input::getVar('frameId', 0)); 
        //remove frame   
        $frame = $dfModel->getFrame($frameId);
        $dfModel->removeFrame($frameId);
        //log change
        ADS_Logger::logChange('Frame "%s" was removed.', $frame['name']);
        //redir
        ADS_Navigator::redir('self:defaultAction',array(
            'msg' => self::STATUS_REMOVE_OK
        ));
    }
    
    public function handleRemoveItem($itemId = 0, $useToken = true){        
        //validate parameters
        if(!is_int($itemId) || !is_bool($useToken)){
            throw new InvalidArgumentException(sprintf('Wrong parameters for method %s.',__METHOD__));
        }
        //validate token
        if($useToken && !wp_verify_nonce(ADS_Input::getVar('token', ''), $_GET['page'].':removeItem')){
            throw new ADS_VerifyTokenException('Token mismatch.');
        }
        $dfiModel = new ADS_DataFrameItemModel();
        //get variables
        $itemId = (int)_ifset($itemId > 0, $itemId, ADS_Input::getVar('itemId', 0)); 
        //remove frame
        $item = $dfiModel->getItem($itemId);
        $dfiModel->removeItem($itemId);
        //log change
        ADS_Logger::logChange('Item "%s" was removed.', $item['name']);
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_REMOVE_OK
        ), 'frameId');
    }
    
    public function handleIncreaseItemPosition(){  
        $itemId = (int)ADS_Input::getVar('itemId', 0);
        //increase position
        $dfiModel = new ADS_DataFrameItemModel();
        $dfiModel->increaseItemPosition($itemId);
        //log change
        $item = $dfiModel->getItem($itemId);
        ADS_Logger::logChange('Position of item "%s" was changed.', $item['name']);
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_INCREASE_OK
        ), 'frameId');
    }
    
    public function handleDecreaseItemPosition(){        
        $itemId = (int)ADS_Input::getVar('itemId', 0);
        //decrease position
        $dfiModel = new ADS_DataFrameItemModel();
        $dfiModel->decreaseItemPosition($itemId);
        //log change
        $item = $dfiModel->getItem($itemId);
        ADS_Logger::logChange('Position of item "%s" was changed.', $item['name']);
        //redir
        ADS_Navigator::redir('self:editItems',array(
            'msg' => self::ITEM_DECREASE_OK
        ), 'frameId');
    }
    
    public function handleAddFrame(){
        
        $dfModel = new ADS_DataFrameModel();
        //default values
        $frame   = array();
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'add':
                $frame['name']   = (string)ADS_Input::postVar('frame.name', '');
//                $frame['htmlId'] = (string)ADS_Input::postVar('frame.htmlId', '');
                //validation
                if(mb_strlen($frame['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of frame can not be blank.'));
                    $isValid = false;
                }                
                if(mb_strlen($frame['name']) > 0 && (mb_strlen($frame['name']) < 4 || mb_strlen($frame['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of frame must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }
//                if(mb_strlen($frame['htmlId']) == 0){
//                    ADS_MsgStack::push('error', sprintf('ID of container can not be blank.'));
//                    $isValid = false;
//                }
                
                if($isValid){
                    //insert new frame to db
                    $dfModel->addFrame(array(
                        'name' => $frame['name']
                    ));
                    //log change
                    ADS_Logger::logChange('Frame "%s" was created.', $frame['name']);
                    //redir
                    ADS_Navigator::redir('self:defaultAction',array(
                        'msg' => self::STATUS_ADD_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('frame', $frame);
        ADS_Output::register('errors', $errors);
        
    }
    
    public function handleEditFrame(){
        
        $dfModel = new ADS_DataFrameModel();
        //default values
        $frameId = (int)ADS_Input::getVar('frameId', 0);
        $frame   = $dfModel->getFrame($frameId);
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'edit':
                $frame = array();
                //get values
                $frame['name']   = (string)ADS_Input::postVar('frame.name', '');
//                $frame['htmlId'] = (string)ADS_Input::postVar('frame.htmlId', '');
                //validation
                if(mb_strlen($frame['name']) == 0){
                    ADS_MsgStack::push('error', sprintf('Name of frame can not be blank.'));
                    $isValid = false;
                }                
                if(mb_strlen($frame['name']) > 0 && (mb_strlen($frame['name']) < 4 || mb_strlen($frame['name']) > 255)){
                    ADS_MsgStack::push('error', sprintf('Name of frame must be between %d and %d characters long.', 4, 255));
                    $isValid = false;
                }
//                if(mb_strlen($frame['htmlId']) == 0){
//                    ADS_MsgStack::push('error', sprintf('ID of container can not be blank.'));
//                    $isValid = false;
//                }
                //ready to go
                if($isValid){
                    //insert new frame to db
                    $dfModel->editFrame($frameId, array(
                        'name' => $frame['name']
                    ));
                    //log change
                    ADS_Logger::logChange('Frame "%s" was updated.', $frame['name']);
                    //redir
                    ADS_Navigator::redir('self:defaultAction',array(
                        'msg' => self::STATUS_EDIT_OK
                    ));
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('frame', $frame);
        ADS_Output::register('errors', $errors);
        
    }
    
    public function handleEditItems(){
        
        //default values
        $page    =    (int)ADS_Input::getVar('paged', 1);
        $orderBy = (string)ADS_Input::getVar('orderBy', 'position');
        $order   = (string)ADS_Input::getVar('order', 'ASC');
        $frameId =    (int)ADS_Input::getVar('frameId', 0);
        $item    = array();        
        //prepare filter
        $status = (string)ADS_Input::getVar('status_valid', '-1');
        $filter = array(
            'now' => array(
                array('validFrom <= NOW()'),
                array('validTo >= NOW()')
            ),
            'future' => array(
                array('validFrom > NOW()')
            ),
            'past' => array(
                array('validTo < NOW()')
            ),
        );
        //load sources
        $dfModel  = new ADS_DataFrameModel();
        $dfiModel = new ADS_DataFrameItemModel();
        $dsModel  = new ADS_DataSourceModel();
        //resolve action
        $action = ADS_Input::postVar('action', 'default'); 
        //execute action
        switch ($action) {
            case 'add':
                $isValid = true;
                //values
                $item['frameId']   = $frameId;
                //get values
                $item['sourceId']  =    (int)ADS_Input::postVar('item.sourceId', -1);
                $item['validFrom'] = (string)ADS_Input::postVar('item.validFrom', date('Y/m/d'));
                $item['validTo']   = (string)ADS_Input::postVar('item.validTo', date('Y/m/d'));   
                //validate
                if(!ads_checkdate($item['validFrom']) || !ads_checkdate($item['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new item to timeline
                    $dfiModel->addItem($item);
                    //log change
                    ADS_Logger::logChange('Item "%s" was inserted.', $item['name']);
                    //redir
                    ADS_Navigator::redir('self:editItems',array(
                        'msg' => self::ITEM_ADD_OK                        
                    ), 'frameId');
                }

                break;
        }
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'position', 'validFrom', 'validTo'
        ));
        //count records
        $cnt = (int)$dfiModel->setFilter((array)@$filter[$status])->countItems($frameId);
        //output
        ADS_Output::register('item', $item);
        ADS_Output::register('frame',$dfModel->getFrame($frameId));
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $dfiModel->getLimit(), $cnt)
        );
        ADS_Output::register(
            'frame_items', 
            $dfiModel->setFilter((array)@$filter[$status])->setSorter($rules)->setPager($page)->getItems($frameId)
        );
        ADS_Output::register(
            'cnt',
            array(
                'all'    => $dfiModel->setFilter(array())->countItems($frameId),
                'now'    => $dfiModel->setFilter($filter['now'])->countItems($frameId),
                'future' => $dfiModel->setFilter($filter['future'])->countItems($frameId),
                'past'   => $dfiModel->setFilter($filter['past'])->countItems($frameId)
            )            
        );
        ADS_Output::register('data_sources', ads_prepare_options(
            $dsModel->getSources(), 'sourceId', 'name'
        ));
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::ITEM_ADD_OK){
            ADS_MsgStack::push('success', 'Source was successfully inserted.');
        }
        if($msg === self::ITEM_REMOVE_OK){
            ADS_MsgStack::push('success', 'Source was successfully removed.');
        }
        if($msg === self::ITEM_DECREASE_OK){
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
        if($msg === self::ITEM_INCREASE_OK){
            ADS_MsgStack::push('success', 'Position was successfully changed.');
        }
    }
    
    public function handleEditItem(){
        
        $dfiModel = new ADS_DataFrameItemModel();
        //default values
        $itemId = (int)ADS_Input::getVar('itemId', 0);
        $item   = $dfiModel->getItem($itemId);        
        $isValid = true;
        //resolve action
        $action = ADS_Input::postVar('action', 'default');         
        switch($action){
            case 'edit':
                $name = $item['name'];
                $item = array();
                //get values
                $item['position']  =    (int)ADS_Input::postVar('item.position', -1);
                $item['validFrom'] = (string)ADS_Input::postVar('item.validFrom', date('Y/m/d'));
                $item['validTo']   = (string)ADS_Input::postVar('item.validTo', date('Y/m/d'));   
                //validate
                if(!ads_checkdate($item['validFrom']) || !ads_checkdate($item['validTo'])){
                    ADS_MsgStack::push('error', sprintf('Wrong format of date. Must be dd/mm/yyyy.'));
                    $isValid = false;
                }
                //validation
                if($item['position'] === -1){
                    ADS_MsgStack::push('error', sprintf('Position can not be blank.'));
                    $isValid = false;
                }
                //ready to go
                if($isValid){
                    //insert new frame to db
                    $dfiModel->editItem($itemId, $item);
                    //log change
                    ADS_Logger::logChange('Item "%s" was updated.', $name);
                    //redir
                    ADS_Navigator::redir('self:editItems',array(
                        'msg' => self::ITEM_EDIT_OK
                    ), 'frameId');
                }                
                break;                
        }  
        //add variables to output
        ADS_Output::register('item', $item);
        ADS_Output::register('errors', $errors);
        
    }
    
    public function handleDefaultAction(){
        //get variables
        $page    =    (int)ADS_Input::getVar('paged', 1);
        $orderBy = (string)ADS_Input::getVar('orderBy', '');
        $order   = (string)ADS_Input::getVar('order', 'ASC');
        //prepare sorting
        $rules = ads_prepare_sorting($orderBy, $order, array(
            'name', 'htmlId'
        ));
        //load frames
        $dfModel = new ADS_DataFrameModel();
        //count records
        $cnt = (int)$dfModel->countFrames();
        ADS_Output::register(
            'frames',
            $dfModel->setSorter($rules)->setPager($page)->getFrames()
        );
        ADS_Output::register(
            'pager',
            ads_prepare_paging($page, $dfModel->getLimit(), $cnt)
        );
        //restore message
        $msg = (int)ADS_Input::getVar('msg', -1);
        if($msg === self::STATUS_ADD_OK){
            ADS_MsgStack::push('success', 'Frame was successfully inserted.');
        }
        if($msg === self::STATUS_EDIT_OK){
            ADS_MsgStack::push('success', 'Frame was successfully updated.');
        }
        if($msg === self::STATUS_REMOVE_OK){
            ADS_MsgStack::push('success', 'Frame was successfully removed.');
        }        
    }
    
}